package com.netty.server.handler;

import cn.hutool.core.util.HexUtil;
import com.netty.server.base.ConnectionAttr;
import com.netty.server.cmd.ByteCmd;
import com.netty.server.cmd.ByteResCmd;
import com.netty.server.cmd.LoginCmd;
import com.netty.server.processor.UpProcessor;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Objects;

/**
 * 处理ByteCmd指令的处理器
 * 既是上行解码器,又是下行编码器
 *
 * @author: 王霄
 * @date: 2022/1/17 14:07
 **/
@Slf4j
public class ByteCmdHandler extends MessageToMessageCodec<ByteCmd, ByteCmd> {

    private final UpProcessor upProcessor;

    public ByteCmdHandler(UpProcessor upProcessor) {
        this.upProcessor = upProcessor;
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, ByteCmd byteCmd, List<Object> list) throws Exception {
        byte[] data = byteCmd.serializer();
        log.info("发送数据包: [{}]", HexUtil.encodeHexStr(data));
        list.add(Unpooled.wrappedBuffer(data));
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteCmd byteCmd, List<Object> list) {
        //如果是登录指令就分发给登录处理器
        if (byteCmd.isLogin()) {
            list.add(LoginCmd.deserialize(byteCmd));
            return;
        }

        //否则需要判断是否登录成功,即管道内是否含有连接ID
        String mac = ctx.channel().attr(ConnectionAttr.MAC).get();
        if (Objects.nonNull(mac)) {
            log.info("处理客户端上行事件,mac=[{}], cmdType=[{}]", mac, byteCmd.getCmdType());
            //ACK响应
            if (byteCmd.isNeedAck()) {
                ByteResCmd resCmd = ByteResCmd.build(byteCmd, ByteResCmd.Code.OK);
                ctx.channel().writeAndFlush(resCmd);
            }
            upProcessor.processor(byteCmd);
        } else {
            log.info("客户端未登录,remoteAddress=[{}]", ctx.channel().remoteAddress());
            ByteResCmd resCmd = ByteResCmd.build(byteCmd, ByteResCmd.Code.FAIL);
            ctx.channel().writeAndFlush(resCmd);
        }
    }
}
